/* 
 * AgenteSaveRule.java
 * 
 * Data de criação: 12/10/2010
 * 
 * O2 SOLUTIONS - SOLUÇÕES EM TECNOLOGIA DA INFORMAÇÃO. 
 *
 */
package br.com.o2solutions.siso.business.rule.agente;

import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import br.com.o2solutions.core.exception.BusinessException;
import br.com.o2solutions.core.integration.repository.DataBaseIntegration;
import br.com.o2solutions.core.service.rule.Rule;
import br.com.o2solutions.siso.integration.entidade.Agente;
import br.com.o2solutions.siso.integration.entidade.Contato;
import br.com.o2solutions.siso.integration.entidade.enumerator.TipoContatoEnumerator;
import br.com.o2solutions.util.assertion.Assert;
import br.com.o2solutions.util.collection.CollectionUtil;
import br.com.o2solutions.util.lang.StringUtil;

/**
 * Classe responsável por realizar a validação do {@link Agente} antes do
 * processo de persistencia ou atualização na base de dados.
 * 
 * @author osvaldeir
 * @since 12/10/2010
 * 
 */
@Component("agenteSaveRule")
public class AgenteInsertUpdateRule implements Rule<Agente> {

	@Value("#{agenteDAO}")
	private DataBaseIntegration<Agente> agenteDAO;

	/**
	 * {@inheritDoc} Neste caso se o {@link Agente} a ser persistido não está
	 * duplicando um dos seguintes atributos:
	 * <ul>
	 * <li>Contato (email)</li>
	 * <li>Matrícula</li>
	 * </ul>
	 * Caso um desses atributos esteja duplicado é lançada uma
	 * {@link BusinessException} informando a quebra da regra negocial com a
	 * mensagem e chave respectiva da exceção.
	 */
	@Override
	public void check(Agente entity) throws BusinessException {
		verificaContato(entity);
		verificaEndereco(entity);
		List<Agente> resultListByMatricula = agenteDAO.findByNamedQuery(
				"Agente.findByMatricula", entity.getMatricula());
		resultListByMatricula.remove(entity);
		Assert.isEmpty(resultListByMatricula, new BusinessException(
				"A matricula informada para o agente já está cadastrada",
				"error.agente.matricula.duplicated"));
		List<Contato> contatos = entity.getContatos();
		if (!CollectionUtil.isEmpty(contatos)) {
			for (Contato contato : contatos) {
				if (TipoContatoEnumerator.EMAIL
						.equals(contato.getTipoContato())) {
					List<Agente> resultListByEmail = agenteDAO
							.findByNamedQuery("Agente.findAgenteByEmail",
									contato.getValor());
					resultListByEmail.remove(entity);
					Assert.isEmpty(
							resultListByEmail,
							new BusinessException("Email já cadastrado",
									"error.agente.email.duplicated", contato
											.getValor()));
				}
			}
		}
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * É obrigado a informar pelo menos um contato para o agente, caso não informe
	 * será lançada uma {@link BusinessException} com a chave
	 * <b>error.required.field.agente.contato</b>.
	 * </p>
	 */
	public void verificaContato(Agente entity) {
		List<Contato> contatos = entity.getContatos();
		Assert.isTrue(contatos.size() > 0, new BusinessException(
				"É necessário o preenchimento de pelo menos um contato.",
				"error.required.field.agente.contato"));
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * O campo endereço é de preenchimento obrigatório, caso não informe
	 * será lançada uma {@link BusinessException} com a chave
	 * <b>error.required.field.agente.endereco</b>.
	 * </p>
	 */
	public void verificaEndereco(Agente entity) {
		Assert.isTrue(!(entity.getEndereco().equals(null) || entity
				.getEndereco().equals("")), new BusinessException(
				"O campo endereço é obrigatório o preenchimento.",
				"error.required.field.agente.endereco", entity.getEndereco()));
	}

}
